package org.chartsy.annotation.arrowline;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Stroke;
import java.awt.geom.Point2D;
import java.io.Serializable;
import org.chartsy.main.ChartFrame;
import org.chartsy.main.chart.Annotation;
import org.chartsy.main.utils.CoordCalc;
import org.chartsy.main.utils.SerialVersion;
import org.openide.nodes.AbstractNode;
/**
*
* @author viorel.gheba
*/
public class ArrowLine
extends Annotation
implements Serializable
{
private static final long serialVersionUID = SerialVersion.APPVERSION;
private AnnotationProperties properties;
private double arrowPosition = 1;
private double arrowSize = 14;
private double arrowAngle = Math.atan(1) * 2 / 5;
public ArrowLine()
{ super(); }
public ArrowLine(ChartFrame frame)
{
super(frame);
actionSet.set(TOP_LEFT);
actionSet.set(BOTTOM_RIGHT);
properties = new AnnotationProperties();
}
public @Override String getName()
{ return "Arrow Line"; }
public Annotation newInstance(ChartFrame frame)
{ return new ArrowLine(frame); }
public boolean pointIntersects(double x, double y)
{ return (getActionPoint(x, y) != NONE) || lineContains(getP1(), getP2(), new Point2D.Double(x, y), 4); }
public void paint(Graphics2D g) {
Stroke old = g.getStroke();
g.setPaint(properties.getColor());
g.setStroke(properties.getStroke());
Point2D p1 = getP1();
Point2D p2 = getP2();
g.draw(CoordCalc.line(p1, p2));
paintArrow(g);
g.setStroke(old);
if (isSelected())
paintActionPoints(g);
}
private void paintArrow(Graphics2D g)
{
double X1 = getXFromTime(getT1()), X2 = getXFromTime(getT2());
double Y1 = getYFromValue(getV1()), Y2 = getYFromValue(getV2());
double arrowHeadX = X1 + (X2 - X1) * arrowPosition;
double arrowHeadY = Y1 + (Y2 - Y1) * arrowPosition;
double alpha = Math.asin((Y2 - Y1) / Math.sqrt(Math.pow(X2 - X1, 2) + Math.pow((Y2 - Y1), 2)));
double absoluteAngle1 = X2 > X1 ? Math.PI + (alpha - arrowAngle) : arrowAngle - alpha;
double firstArrowTailX = arrowHeadX + arrowSize * Math.cos(absoluteAngle1);
double firstArrowTailY = arrowHeadY + arrowSize * Math.sin(absoluteAngle1);
double absoluteAngle2 = X2 > X1 ? Math.PI + (alpha + arrowAngle) : -arrowAngle - alpha;
double secondArrowTailX = arrowHeadX + arrowSize * Math.cos(absoluteAngle2);
double secondArrowTailY = arrowHeadY + arrowSize * Math.sin(absoluteAngle2);
g.draw(CoordCalc.line(firstArrowTailX, firstArrowTailY, arrowHeadX, arrowHeadY));
g.draw(CoordCalc.line(secondArrowTailX, secondArrowTailY, arrowHeadX, arrowHeadY));
}
protected @Override void updateRectangles(long oldT1, long newT1, long oldT2, long newT2, double oldV1, double newV1, double oldV2, double newV2)
{
Rectangle r;
r = getRectangle(oldT1, oldV1, oldT2, oldV2);
Rectangle r1 = new Rectangle();
r1.setFrameFromDiagonal(r.getMinX(), r.getMinY(), r.getMaxX(), r.getMaxY());
r1.grow(3, 3);
addUpdateRectangle(r1, false);
r = getRectangle(newT1, newV1, newT2, newV2);
Rectangle r2 = new Rectangle(); r2.setFrameFromDiagonal(r.getMinX(), r.getMinY(), r.getMaxX(), r.getMaxY());
r2.grow(3, 3);
addUpdateRectangle(r2, false);
}
public AbstractNode getNode()
{ return new AnnotationNode(properties); }
}